<?php

namespace tmcore\services;

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception as MailerException;
use tmcore\exceptions\MsgException;

/**
 * 邮件发送类
 * 支持发送纯文本邮件和HTML格式的邮件，可以多收件人，多抄送，多秘密抄送，带附件的邮件
 * @example
 * $mail = new MailService();
 * $mail->setFrom("XXXXX","XXXXX"); 设置发件人
 * $mail->setReceiver("XXXXX","XXXXX"); 设置收件人
 * $mail->setCc("XXXXX","XXXXX"); 设置抄送
 * $mail->setBcc("XXXXX","XXXXX"); 设置秘密抄送
 * $mail->isHTML(false); 设置HTML格式
 * $mail->setAttachment("XXXXX","XXXXX"); 设置附件
 * $mail->setMailInfo("test", "<b>test</b>"); 设置邮件主题、内容
 * $mail->sendMail(); 发送
 */
class MailService
{
    /**
     * 邮件配置信息
     * @var array
     */
     protected array $config = [];

    /**
     * 邮件对象
     * @var PHPMailer
     */
    protected PHPMailer $mail;

    /**
     * 发件人
     * @var array
     */
    protected array $from = [];

    /**
     * 是否是HTML
     * @var bool
     */
    protected bool $isHtml = false;

    /**
     * 初始化
     */
    public function __construct()
    {
        $this->mail = new PHPMailer();
        $this->config = (new ConfigService)->getConfig('mail', 'sys');
    }

    /**
     * 发送邮件
     * @return bool
     * @throws MailerException
     * @throws MsgException
     */
    public function sendMail()
    {
        $this->mail->CharSet = "UTF-8"; //设置编码
        $this->mail->SMTPDebug = 0; // 启用详细调试输出 2-查看详细 0-关闭
        $this->mail->IsSMTP(); // 使用SMTP方式发送
        $this->mail->SMTPAuth = true; // 启用SMTP验证功能
        $this->mail->Host = $this->config['host'] ?? ''; // 域名
        $this->mail->Username = $this->config['user_name'] ?? ''; // 用户名(完整的email地址)
        $this->mail->Password = $this->config['password'] ?? ''; // 密码
        $this->mail->Port = $this->config['port'] ?? 25; // 端口
        $this->mail->SMTPSecure = $this->config['secure_type'] ?? 'tls'; // 允许协议[tls/ssl]
        $this->mail->SMTPOptions = [
            'ssl' => [
                'verify_peer'       => false,
                'verify_peer_name'  => false,
                'allow_self_signed' => true,
            ],
        ];

        // 设置发件人
        if($this->from) {
            $this->mail->From = $this->from['address'] ?? ''; // 发件人email地址
            $this->mail->FromName = $this->from['name'] ?? ''; // 发件人名称
        } else {
            $this->mail->From = $this->config['form_address'] ?? '';
            $this->mail->From = $this->config['form_name'] ?? '';
        }

        // 发送
        $status = $this->mail->send();
        if (!$status) {
            throw new MsgException($this->mail->ErrorInfo);
        }
        return true;
    }

    /**
     * 设置发件人
     * @param string $address 地址
     * @param string $name 名称
     * @return bool
     */
    public function setFrom($address, $name = '')
    {
        $this->from = ['address'=>$address, 'name'=>$name];
        return true;
    }

    /**
     * 设置收件人，多个收件人，连续调用多次
     * @param string $address 地址
     * @param string $name 名称
     * @return $this
     * @throws MailerException
     */
    public function setReceiver($address, $name = '')
    {
        $this->mail->addAddress($address, $name);
        return $this;
    }

    /**
     * 设置抄送，多个抄送，连续调用多次
     * @param string $address 地址
     * @param string $name 名称
     * @return $this
     * @throws MailerException
     */
    public function setCc($address, $name = '')
    {
        $this->mail->addCC($address, $name);
        return $this;
    }

    /**
     * 设置秘密抄送，多个秘密抄送，连续调用多次
     * @param string $address 地址
     * @param string $name 名称
     * @return $this
     * @throws MailerException
     */
    public function setBcc($address, $name = '')
    {
        $this->mail->addBCC($address, $name);
        return $this;
    }

    /**
     * 设置HTML格式
     * @param bool $isHtml
     * @return $this
     */
    public function isHTML($isHtml = true)
    {
        $this->isHtml = $isHtml;
        $this->mail->isHTML($isHtml);
        return $this;
    }

    /**
     * 设置邮件信息
     * @param string $subject 邮件主题
     * @param string $body 邮件主体内容，可以是纯文本，也可是是HTML文本
     * @return $this
     */
    public function setMailInfo($subject, $body)
    {
        $this->mail->Subject = $subject;
        $this->mail->Body = $body;
        if(!$this->isHtml) $this->mail->AltBody = $body;

        return $this;
    }

    /**
     * 设置附件信息
     * @param string $path 路径
     * @param string $name 名称
     * @return $this
     * @throws MailerException
     */
    public function setAttachment($path, $name = '')
    {
        $this->mail->addAttachment($path, $name);
        return $this;
    }

}